//
//  UIImage+JW.swift
// @project：JWHelperKit
// @author：linjw(10126121@qq.com)
// @time: 2022/12/20
// Copyright © 2018年 Linjw. All rights reserved.
//

import UIKit
import Foundation
import CoreGraphics

@objc public enum iOSAppLaunchImageType: Int {
    case image
    case xib
}

public enum GradientDirection {
    case leftToRight
    case topToBottom
    case topLeftToBottomRight
    case botomLeftToTopRight
    case custom(CGPoint, CGPoint)
}


/// 拓展UIImage
public extension JWNamespaceWrapper where T: UIImage {
    
    /// 模板图
    var imageTemplate: UIImage { return jwWrappedValue.withRenderingMode(.alwaysTemplate) }
    
    /// 原图
    var imageOriginal: UIImage { return jwWrappedValue.withRenderingMode(.alwaysOriginal) }
    
    /// 数据大小
    var bytesSize: Int { return jwWrappedValue.jpegData(compressionQuality: 1)?.count ?? 0 }
    
    /// 等比例缩放
    func jpegData(maxBytesSize: Int) -> Data? { return jwWrappedValue.jpegData(compressionQuality: jwWrappedValue.jw.ratioValue(compressionBytesSize: maxBytesSize)) }
    
    /// 当前图片大小跟compressionBytesSize的比例
    func ratioValue(compressionBytesSize: Int) -> CGFloat {
        let oriSize = self.bytesSize
        if oriSize > 0, oriSize > compressionBytesSize {
            return CGFloat(compressionBytesSize) / CGFloat(oriSize)
        }
        return 1
    }
    
    /// 九宫格拉伸
    var resizable: UIImage {
        let widthFloat = floor(jwWrappedValue.size.width / 2)
        let heightFloat = floor(jwWrappedValue.size.height / 2)
        return jwWrappedValue.resizableImage(withCapInsets: UIEdgeInsets(top: heightFloat, left: widthFloat, bottom: heightFloat, right: widthFloat))
    }
    
    /// Base64 String
    var base64: String { return jwWrappedValue.jpegData(compressionQuality: 1)?.base64EncodedString() ?? "" }
    
    /// 更改图片颜色
    func image(tintColor color: UIColor) -> UIImage {
        
        UIGraphicsBeginImageContextWithOptions(jwWrappedValue.size, false, jwWrappedValue.scale)
        color.setFill()
        guard let context = UIGraphicsGetCurrentContext() else { return jwWrappedValue }
        
        context.translateBy(x: 0, y: jwWrappedValue.size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        context.setBlendMode(CGBlendMode.normal)
        
        let rect = CGRect(x: 0, y: 0, width: jwWrappedValue.size.width, height: jwWrappedValue.size.height)
        guard let mask = jwWrappedValue.cgImage else { return jwWrappedValue }
        context.clip(to: rect, mask: mask)
        context.fill(rect)
        
        let newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
        
    }
    
    /// 填充透明区域颜色
    func image(fillColor: UIColor) -> UIImage { return jwWrappedValue.image(fillColor: fillColor) }
    
    /// 通过颜色，生成图片
    static func image(fromColor color: UIColor, size: CGSize = CGSize(width: 1, height: 1), cornerRadius: CGFloat = 0) -> UIImage {
        
        let width = max(size.width, CGFloat(cornerRadius * 2 + 1))
        let height = max(size.height, CGFloat(cornerRadius * 2 + 1))
        let rect = CGRect(x: 0, y: 0, width: width, height: height)
        
        let roundedRect = UIBezierPath(roundedRect: rect, cornerRadius: CGFloat(cornerRadius))
        roundedRect.lineWidth = 0
        
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
        
        color.setFill()
        roundedRect.fill()
        roundedRect.stroke()
        roundedRect.addClip()
        
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image.resizableImage(withCapInsets: UIEdgeInsets(top: CGFloat(cornerRadius), left: CGFloat(cornerRadius), bottom: CGFloat(cornerRadius), right: CGFloat(cornerRadius)))
    }
    
    /// 渐变图片
    static func imageGradient(from: UIColor, to: UIColor, direction: GradientDirection, size: CGSize) -> UIImage {
        return UIImage.gradientImage(from: from, to: to, direction: direction, size: size)
    }
    
    /// 设置图片圆角
    func roundImage(roundingCorners: UIRectCorner = UIRectCorner.allCorners, cornerRadii: CGSize) -> UIImage? {
        return jwWrappedValue.roundImage(roundingCorners: roundingCorners, cornerRadii: cornerRadii)
    }
    
    /// 改变图片大小，建议直接用.kf.resize(to:for:)
    func image(resize size: CGSize) -> UIImage {
        
        UIGraphicsBeginImageContext(size)
        jwWrappedValue.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return scaledImage!
        
    }
    
    /// 倒三角图片
    static func imageNabla(size: CGSize, tintColor: UIColor) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        
        let path = UIBezierPath()
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: size.width / 2.0, y: size.height))
        path.addLine(to: CGPoint(x: size.width, y: 0))
        path.close()
        
        context.setFillColor(tintColor.cgColor)
        path.fill()
        
        let toImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return toImage

    }
    
    /// 获取启动图
    static func imageLaunch(type: iOSAppLaunchImageType) -> UIImage? {
        switch type {
        case .xib:
            guard let launchStoryboardName = Bundle.main.infoDictionary?["UILaunchStoryboardName"],
                  let launchStoryboardNameString = launchStoryboardName as? String,
                  let launchScreenSb = UIStoryboard(name: launchStoryboardNameString, bundle: nil).instantiateInitialViewController(),
                  let temView = launchScreenSb.view
            else {
                     return nil
            }
            let containerWindow = UIWindow(frame: UIDevice.jw.screen.bounds)
             temView.frame = CGRect(x: 0, y: 0, width: containerWindow.bounds.width, height: containerWindow.bounds.height)
             containerWindow.addSubview(temView)
             containerWindow.layoutIfNeeded()
             let image = imageFromView(view: temView)
            return image
        case .image:
           let imagePortrait = imageLaunchFromImageType(isLandscape: false)
            if imagePortrait != nil { return imagePortrait! }
            return imageLaunchFromImageType(isLandscape: true)
        }
    }
    
    private static func imageLaunchFromImageType(isLandscape: Bool) -> UIImage? {
        let screenScale = UIDevice.jw.screen.scale
        let screenDipSize = CGSize(width: UIDevice.jw.screen.bounds.size.width * screenScale, height: UIDevice.jw.screen.bounds.size.height * screenScale)
        let viewOrientation = isLandscape ? "Landscape" : "Portrait"
        guard let imagesDict = Bundle.main.infoDictionary?["UILaunchImages"] as? [[String: Any]] else { return nil }
        for dict in imagesDict {
            if let imageName = dict["UILaunchImageName"] as? String, let image = UIImage(named: imageName) as? UIImage, let cgImage = image.cgImage {
                var imageDpiSize = CGSize.zero
                if let imageOrientation = dict["UILaunchImageOrientation"] as? String, viewOrientation == imageOrientation {
                    if isLandscape {
                        imageDpiSize = CGSize(width: cgImage.height, height: cgImage.width)
                    } else {
                        imageDpiSize = CGSize(width: cgImage.width, height: cgImage.height)
                    }
                    if screenDipSize.equalTo(imageDpiSize) {
                        return image
                    }
                }
            }
        }
        return nil
    }

    /// 生成图片
    private static func imageFromView(view: UIView) -> UIImage? {
        if CGRectIsEmpty(view.frame) { return nil }
        let size = view.bounds.size
        UIGraphicsBeginImageContextWithOptions(size, false, UIDevice.jw.screen.scale)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        view.layer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    
    /// 保存图片到相册
    static func saveToPhotoAlbum(image: UIImage, resultAction: ((Bool, Error?) -> ())?) {
        AlbumWriter.save(image, resultAction: resultAction)
    }
    
    /// 保存图片到相册
    func saveToPhotoAlbum(resultAction: ((Bool, Error?) -> ())?) {
        UIImage.jw.saveToPhotoAlbum(image: jwWrappedValue, resultAction: resultAction)
    }
    
}

// MARK: - 扩展
public extension UIImage {
    

    /// 生成颜色渐变图
    static func gradientImage(from starColor: UIColor,
                              to endColor: UIColor,
                              direction: GradientDirection = .leftToRight,
                              size: CGSize = CGSize(width: 200, height: 200)) -> UIImage {
        defer {
            UIGraphicsEndImageContext()
        }
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [starColor.cgColor, endColor.cgColor]
        gradientLayer.locations = [0, 1]
        switch direction {
        case .leftToRight:
            gradientLayer.startPoint = CGPoint(x: 0, y: 0)
            gradientLayer.endPoint = CGPoint(x: 1, y: 0)
        case .topToBottom:
            gradientLayer.startPoint = CGPoint(x: 0, y: 0)
            gradientLayer.endPoint = CGPoint(x: 0, y: 1)
        case .topLeftToBottomRight:
            gradientLayer.startPoint = CGPoint(x: 0, y: 0)
            gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        case .botomLeftToTopRight:
            gradientLayer.startPoint = CGPoint(x: 0, y: 1)
            gradientLayer.endPoint = CGPoint(x: 1, y: 0)
        case let .custom(startPoint, endPoint):
            gradientLayer.startPoint = startPoint
            gradientLayer.endPoint = endPoint
        }
        gradientLayer.frame = CGRect(origin: CGPoint.zero, size: size)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        guard let contenxt = UIGraphicsGetCurrentContext() else {
            return UIImage()
        }
        gradientLayer.render(in: contenxt)
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
            return UIImage()
        }
        return image
    }
    
    /// 截图
    class func screenshot(fromView fv: UIView) -> UIImage {
        
        UIGraphicsBeginImageContextWithOptions(fv.bounds.size, fv.isOpaque, 0.0)
        fv.drawHierarchy(in: fv.bounds, afterScreenUpdates: true)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return img ?? UIImage()
    }
    
    /// 保存图片到相册
    static func saveToPhotoAlbum(image: UIImage, resultAction: ((Bool, Error?) -> ())?) {
        AlbumWriter.save(image, resultAction: resultAction)
    }
    
    fileprivate func image(fillColor: UIColor) -> UIImage {
        
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        let context = UIGraphicsGetCurrentContext()!
        
        let rect = CGRect(origin: CGPoint.zero, size: size)
        
        fillColor.setFill()
        
        context.fill(rect)
        context.setBlendMode(.copy)
        self.draw(in: rect)
        
        let resultImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return resultImage
    }
    
    public func roundImage(roundingCorners: UIRectCorner = UIRectCorner.allCorners, cornerRadi: CGFloat) -> UIImage? {
        return roundImage(roundingCorners: roundingCorners, cornerRadii: CGSize(width: cornerRadi, height: cornerRadi))
    }
    
    public func roundImage(roundingCorners: UIRectCorner = UIRectCorner.allCorners, cornerRadii: CGSize) -> UIImage? {
        
        let imageRect = CGRect(origin: CGPoint.zero, size: size)
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        defer {
            UIGraphicsEndImageContext()
        }
        let context = UIGraphicsGetCurrentContext()
        guard context != nil else {
            return nil
        }
        context?.setShouldAntialias(true)
        let bezierPath = UIBezierPath(roundedRect: imageRect,
                                      byRoundingCorners: roundingCorners,
                                      cornerRadii: cornerRadii)
        bezierPath.close()
        bezierPath.addClip()
        self.draw(in: imageRect)
        return UIGraphicsGetImageFromCurrentImageContext()
    }

    
}

fileprivate class AlbumWriter: NSObject {
    
    typealias Action = (NSError?)->Void
    
    private var callback: Action
    
    private init(callback: @escaping Action) { self.callback = callback }
    
    @objc func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
        callback(error)
    }
    
    static func save(_ image: UIImage, resultAction: ((Bool, Error?) -> ())?) {
        
        let writer = AlbumWriter {  error in
            resultAction?(error == nil, error)
        }
        
        UIImageWriteToSavedPhotosAlbum(image, writer, #selector(AlbumWriter.image(_:didFinishSavingWithError:contextInfo:)), nil)
    
    }
}

